<template>
  <!-- 全屏黑色背景的扫码界面，类似微信/QQ -->
  <div class="qr-scanner-overlay fixed inset-0 bg-black z-50 flex flex-col items-center">
    <!-- 顶部区域 - 状态栏和关闭按钮 -->
    <div class="w-full px-6 py-4 flex justify-end">
      <button 
        v-if="!errorMessage"
        class="w-10 h-10 bg-black/50 rounded-full flex items-center justify-center text-white hover:bg-black/70 transition-colors"
        @click="closeScanner"
      >
        <i class="fa fa-times text-xl"></i>
      </button>
    </div>

    <!-- 主扫描区域 -->
    <div class="relative flex-1 w-full max-w-md flex items-center justify-center">
      <!-- 扫描框 - 更大的尺寸，更明显的边框 -->
      <div v-if="!errorMessage" class="relative w-full aspect-square">
        <!-- 视频元素 - 充满整个背景 -->
        <video ref="video" class="absolute inset-0 w-full h-full object-cover" autoplay muted playsinline></video>
        
        <!-- 扫描区域外的遮罩层 -->
        <div class="absolute inset-0 flex">
          <!-- 顶部遮罩 -->
          <div class="absolute top-0 left-0 right-0 h-[calc(50%-120px)] bg-black/70"></div>
          <!-- 底部遮罩 -->
          <div class="absolute bottom-0 left-0 right-0 h-[calc(50%-120px)] bg-black/70"></div>
          <!-- 左侧遮罩 -->
          <div class="absolute top-0 bottom-0 left-0 w-[calc(50%-120px)] bg-black/70"></div>
          <!-- 右侧遮罩 -->
          <div class="absolute top-0 bottom-0 right-0 w-[calc(50%-120px)] bg-black/70"></div>
        </div>

        <!-- 扫描区域指示器 -->
        <div class="absolute top-[calc(50%-120px)] left-[calc(50%-120px)] w-60 h-60">
          <!-- 扫描线动画 - 更明显的动画效果 -->
          <div class="absolute left-0 right-0 h-0.5 bg-primary shadow-[0_0_10px_1px_rgba(255,107,53,0.8)] animate-scan"></div>
          
          <!-- 扫描区域角落 - 更粗的边框和阴影效果 -->
          <div class="absolute top-0 left-0 w-8 h-8 border-t-4 border-l-4 border-primary shadow-[0_0_10px_rgba(255,107,53,0.8)]"></div>
          <div class="absolute top-0 right-0 w-8 h-8 border-t-4 border-r-4 border-primary shadow-[0_0_10px_rgba(255,107,53,0.8)]"></div>
          <div class="absolute bottom-0 left-0 w-8 h-8 border-b-4 border-l-4 border-primary shadow-[0_0_10px_rgba(255,107,53,0.8)]"></div>
          <div class="absolute bottom-0 right-0 w-8 h-8 border-b-4 border-r-4 border-primary shadow-[0_0_10px_rgba(255,107,53,0.8)]"></div>
          
          <!-- 扫描网格效果 -->
          <div class="absolute inset-0 bg-primary/5 bg-[linear-gradient(transparent_0px,transparent_2px,rgba(255,107,53,0.1)_2px,rgba(255,107,53,0.1)_4px),linear-gradient(90deg,transparent_0px,transparent_2px,rgba(255,107,53,0.1)_2px,rgba(255,107,53,0.1)_4px)] bg-[size:4px_4px]"></div>
        </div>
      </div>
      
      <!-- 错误消息 -->
      <div v-else class="bg-black/30 backdrop-blur-sm rounded-lg p-6 text-center max-w-xs">
        <div class="text-5xl mb-4">
          <i class="fa fa-camera text-primary"></i>
        </div>
        <h3 class="text-white text-xl font-medium mb-2">摄像头访问权限</h3>
        <p class="text-gray-300 mb-6">{{ errorMessage }}</p>
        <div class="flex flex-col gap-3">
          <button 
            class="bg-primary hover:bg-primary/90 text-white py-3 px-6 rounded-full font-medium transition-colors"
            @click="retryScanner"
          >
            重试
          </button>
          <button 
            class="bg-white/10 hover:bg-white/20 text-white py-3 px-6 rounded-full font-medium transition-colors"
            @click="closeScanner"
          >
            取消
          </button>
        </div>
      </div>
    </div>
    
    <!-- 底部区域 - 提示文字和功能按钮 -->
    <div class="w-full px-6 pb-12">
      <!-- 提示文字 -->
      <div v-if="!errorMessage" class="text-center mb-8 text-white">
        <p class="text-lg font-medium mb-2">将二维码/条码放入框内，即可自动扫描</p>
        <p class="text-gray-300 text-sm">保持光线充足，距离5-10厘米</p>
      </div>
      
      <!-- 底部功能按钮 - 类似微信的相册/手电筒按钮 -->
      <div v-if="!errorMessage" class="flex justify-center gap-10">
        <button 
          class="flex flex-col items-center gap-2 text-white"
          @click="toggleFlashlight"
        >
          <div class="w-14 h-14 bg-black/30 rounded-full flex items-center justify-center">
            <i :class="flashlightOn ? 'fa fa-lightbulb-o text-yellow-300' : 'fa fa-lightbulb-o'" text-2xl></i>
          </div>
          <span class="text-sm">手电筒</span>
        </button>
        <button 
          class="flex flex-col items-center gap-2 text-white"
          @click="selectFromAlbum"
        >
          <div class="w-14 h-14 bg-black/30 rounded-full flex items-center justify-center">
            <i class="fa fa-picture-o text-2xl"></i>
          </div>
          <span class="text-sm">相册</span>
        </button>
      </div>
    </div>
  </div>
</template>

<script>
import jsQR from 'jsqr';

export default {
  name: 'QRCodeScanner',
  emits: ['scan-result', 'close'],
  data() {
    return {
      stream: null,
      canvas: null,
      canvasContext: null,
      scanning: false,
      errorMessage: '',
      flashlightOn: false
    };
  },
  mounted() {
    this.initScanner();
  },
  beforeUnmount() {
    this.stopScanner();
  },
  methods: {
    async initScanner() {
      try {
        // 重置错误消息
        this.errorMessage = '';
        
        // 检查浏览器是否支持getUserMedia API
        if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
          this.errorMessage = '您的浏览器不支持摄像头访问功能，请使用现代浏览器重试。';
          console.error('浏览器不支持getUserMedia API');
          return;
        }
        
        // 检查是否在安全上下文(HTTPS)中
        if (window.location.protocol !== 'https:') {
          console.warn('getUserMedia API在非HTTPS环境中可能受限');
        }
        
        // 创建canvas元素用于图像处理
        this.canvas = document.createElement('canvas');
        this.canvasContext = this.canvas.getContext('2d');
        
        // 请求摄像头权限并获取视频流
        // 为移动设备提供更多配置选项以提高兼容性
        this.stream = await navigator.mediaDevices.getUserMedia({
          video: {
            facingMode: { ideal: 'environment' }, // 使用ideal而不是exact以提高兼容性
            width: { ideal: 1280 },
            height: { ideal: 720 },
            frameRate: { ideal: 30, min: 10 }
          }
        });
        
        // 设置视频元素
        const video = this.$refs.video;
        video.srcObject = this.stream;
        
        // 等待视频元数据加载完成
        await new Promise(resolve => {
          video.onloadedmetadata = resolve;
        });
        
        // 设置canvas尺寸
        this.canvas.width = video.videoWidth;
        this.canvas.height = video.videoHeight;
        
        // 开始扫描
        this.scanning = true;
        this.startScanning();
      } catch (error) {
        console.error('初始化扫描器失败:', error);
        
        // 根据错误类型提供更具体的提示
        if (error.name === 'NotAllowedError' || error.name === 'PermissionDeniedError') {
          this.errorMessage = '请在手机设置中允许此应用访问您的摄像头，然后重试。';
        } else if (error.name === 'NotFoundError' || error.name === 'DevicesNotFoundError') {
          this.errorMessage = '未检测到可用的摄像头设备。';
        } else if (error.name === 'NotReadableError') {
          this.errorMessage = '摄像头被其他应用占用，请关闭其他应用后重试。';
        } else if (error.name === 'OverconstrainedError') {
          // 如果严格要求后置摄像头失败，尝试不指定摄像头类型
          try {
            this.stream = await navigator.mediaDevices.getUserMedia({
              video: { width: { ideal: 1280 }, height: { ideal: 720 } }
            });
            const video = this.$refs.video;
            video.srcObject = this.stream;
            await new Promise(resolve => { video.onloadedmetadata = resolve; });
            this.canvas.width = video.videoWidth;
            this.canvas.height = video.videoHeight;
            this.scanning = true;
            this.startScanning();
            return;
          } catch (fallbackError) {
            console.error('使用备用配置也失败:', fallbackError);
            this.errorMessage = '无法访问摄像头，请确保已授予权限并尝试重新打开应用。';
          }
        } else {
          this.errorMessage = '无法访问摄像头，请确保已授予权限。';
        }
      }
    },
    
    retryScanner() {
      // 尝试重新初始化扫描器
      this.initScanner();
    },
    
    startScanning() {
      const scan = () => {
        if (!this.scanning) return;
        
        const video = this.$refs.video;
        
        // 在canvas上绘制当前视频帧
        this.canvasContext.drawImage(video, 0, 0, this.canvas.width, this.canvas.height);
        
        // 获取图像数据
        const imageData = this.canvasContext.getImageData(0, 0, this.canvas.width, this.canvas.height);
        
        // 使用jsQR库解析QR码
        const code = jsQR(imageData.data, imageData.width, imageData.height, {
          inversionAttempts: 'dontInvert',
        });
        
        // 如果解析到QR码
        if (code) {
          this.handleScanResult(code.data);
        } else {
          // 继续扫描
          requestAnimationFrame(scan);
        }
      };
      
      // 开始扫描循环
      requestAnimationFrame(scan);
    },
    
    handleScanResult(result) {
      this.scanning = false;
      this.stopScanner();
      
      // 发射扫描结果事件
      this.$emit('scan-result', result);
      
      // 关闭扫描器
      this.closeScanner();
    },
    
    stopScanner() {
      this.scanning = false;
      
      // 停止视频流
      if (this.stream) {
        this.stream.getTracks().forEach(track => {
          track.stop();
        });
        this.stream = null;
      }
      
      // 清空视频源
      if (this.$refs.video) {
        this.$refs.video.srcObject = null;
      }
    },
    
    closeScanner() {
      this.stopScanner();
      // 重置错误消息
      this.errorMessage = '';
      this.flashlightOn = false;
      this.$emit('close');
    },
    
    // 切换手电筒功能
    async toggleFlashlight() {
      try {
        if (!this.stream) return;
        
        // 获取视频轨道
        const videoTrack = this.stream.getVideoTracks()[0];
        
        // 检查是否支持手电筒
        if (!videoTrack.getCapabilities || !videoTrack.getCapabilities().torch) {
          alert('您的设备不支持手电筒功能');
          return;
        }
        
        // 切换手电筒状态
        this.flashlightOn = !this.flashlightOn;
        await videoTrack.applyConstraints({
          advanced: [{ torch: this.flashlightOn }]
        });
      } catch (error) {
        console.error('切换手电筒失败:', error);
        this.flashlightOn = false;
        alert('无法使用手电筒功能');
      }
    },
    
    // 从相册选择图片功能
    selectFromAlbum() {
      // 创建一个隐藏的文件输入框
      const fileInput = document.createElement('input');
      fileInput.type = 'file';
      fileInput.accept = 'image/*';
      fileInput.style.display = 'none';
      
      // 监听文件选择
      fileInput.addEventListener('change', async (event) => {
        const file = event.target.files[0];
        if (!file) return;
        
        try {
          // 读取图片文件
          const imageData = await this.readImageFile(file);
          // 扫描图片中的二维码
          this.scanImage(imageData);
        } catch (error) {
          console.error('读取图片失败:', error);
          alert('无法读取图片，请选择有效的图片文件');
        }
        
        // 移除临时元素
        document.body.removeChild(fileInput);
      });
      
      // 添加到DOM并触发点击
      document.body.appendChild(fileInput);
      fileInput.click();
    },
    
    // 读取图片文件
    readImageFile(file) {
      return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = (event) => {
          const img = new Image();
          img.onload = () => {
            // 创建canvas并绘制图片
            const canvas = document.createElement('canvas');
            const ctx = canvas.getContext('2d');
            canvas.width = img.width;
            canvas.height = img.height;
            ctx.drawImage(img, 0, 0);
            
            // 获取图像数据
            resolve(ctx.getImageData(0, 0, canvas.width, canvas.height));
          };
          img.onerror = reject;
          img.src = event.target.result;
        };
        reader.onerror = reject;
        reader.readAsDataURL(file);
      });
    },
    
    // 扫描图片中的二维码
    scanImage(imageData) {
      // 使用jsQR库解析QR码
      const code = jsQR(imageData.data, imageData.width, imageData.height, {
        inversionAttempts: 'dontInvert',
      });
      
      if (code) {
        this.handleScanResult(code.data);
      } else {
        alert('未在图片中找到二维码');
      }
    }
  }
};
</script>

<style scoped>
/* 扫描线动画 - 更流畅的动画效果 */
@keyframes scan {
  0% {
    top: 0;
  }
  100% {
    top: 100%;
  }
}

.animate-scan {
  animation: scan 2s linear infinite;
}

/* 适配移动设备的响应式调整 */
@media (max-width: 480px) {
  .absolute.top-\[calc\(50%\-120px\)\].left-\[calc\(50%\-120px\)\].w-60.h-60 {
    width: 240px;
    height: 240px;
    top: calc(50% - 120px);
    left: calc(50% - 120px);
  }
  
  .absolute.top-0.left-0.w-\[calc\(50%\-120px\)\].h-\[calc\(50%\-120px\)\] {
    width: calc(50% - 120px);
    height: calc(50% - 120px);
  }
  
  .absolute.bottom-0.left-0.w-\[calc\(50%\-120px\)\].h-\[calc\(50%\-120px\)\] {
    width: calc(50% - 120px);
    height: calc(50% - 120px);
  }
  
  .absolute.top-0.right-0.w-\[calc\(50%\-120px\)\].h-full {
    width: calc(50% - 120px);
  }
  
  .absolute.bottom-0.right-0.w-\[calc\(50%\-120px\)\].h-full {
    width: calc(50% - 120px);
  }
}
</style>